/** One way list is made for adding unordered short list, 
with small foot print and using simple loop to retrieve its' items. 
If individual item deletion is required recommend to use other library. 
*/
#ifndef _YONEWAYLIST_H
#define _YONEWAYLIST_H
#include <tool/ydefine.h>

/** Function pointers struct, use externally */
typedef struct oneWayList *oneWayList;
/** Data struct, use internally */
typedef struct oneWayListData *oneWayListData;

/** Struct of one way list function pointers */
struct oneWayList {
  /*--- data ---*/
  oneWayListData d;
  /*--- function pointers ---*/
  /** Free this oneWay List from memory.
  <p><b>WARNING:</b> Function will free items in the one way list as well, 
  via the call to <code>boolean (*freeItem)(void **)</code>.
  </p>
  <p>Do NOT free anything taken out of item, 
  e.g. via function pointer call to
  <code>void *(*getItem)(const oneWayList)</code>.
  Because the one way list still points to the item. 
  Thus the item in a sense still sits inside the list so
  it's memory will be free by this function.
  </p>
  <p>However you can free the item IF 
  <ul>
  <li>(1) the item's library say so, such as the item's "free" function 
  which is our function pointer <code>boolean (*freeItem)(void **)</code> 
  couldn't and doesn't handle it.
  Thus requiring external program to handle this.
  e.g. Cloned data struct (which it doesn't keep track of).
  </li>
  <li>(2) You SHOULD free this "cloned" copy of the item cloned from the list.
  The list does NOT keep track of these "clones" and shouldn't release them..
  <br/>UNLESS the item does some trick to <b>keep track of it's own clone</b>, 
  AND also release them via the same function pointer call to 
  <code>boolean (*freeItem)(void **)</code>.
  <br/><b>Advice:</b> Read the item's library for details.
  </li>
  </ul>
  </p>
  @param listP pass in the address of oneWay List struct pointer to be free.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*free)(oneWayList *listP);
  /** Returns the number of elements in this list.
  @param list the one way list.
  @return Returns the number of elements in this list or -1 if failure.
  */
  int (*size)(const oneWayList list);
  /** Removes all of the elements from this list.
  @param list the one way list.
  @return <code>true</code> if successful 
    otherwise <code>false</code> nothing to remove.
  */
  boolean (*clear)(oneWayList list);
  /*--- traverse */
  /** If the list previously point at something.
  Mainly for debugg purpose.
  @param list the one way list.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*previous)(const oneWayList list);
  /** If the list currently point at something.
  @param list the one way list.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*current)(const oneWayList list);
  /** Move to next item. Successful if next in list point at something, 
  otherwise stay at the tail of the list.
  @param list the one way list.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*goNext)(oneWayList list);
  /** Move to the first item in the list. 
  @param list the one way list.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*goFirst)(oneWayList list);
  /*--- test */
  /** Tests if this list has no elements.
  @param list the one way list.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*isEmpty)(const oneWayList list);
  /** Are we currently pointing to the first item in the list?
  @param list the one way list.
  @return true if pointing to the first item, false otherwise.
  */
  boolean (*isFirst)(const oneWayList list);
  /** Are we currently pointing to the last item in the list?
  @param list the one way list.
  @return true if pointing to the last item, false otherwise.
  */
  boolean (*isLast)(const oneWayList list);
  /** Is there another item after current item in the list?
  @param list the one way list.
  @return true if successful, false otherwise.
  */
  boolean (*hasNext)(const oneWayList list);
  /** Compare a given item against the item currently 
  pointing to within in the list.
  <p>MUST provide the function of the form 
  <code>g_reply (*compareItem)(const void *, const void *)</code>.
  through <code>setFnCompareItem(..)</code> beforehand to 
  able to use this function
  </p>
  <p><code>compareItem</code> should return <code>g_replyEqual</code> 
  if <code>anItem</code> and list's item are equal.
  Returns <code>g_replyLesser</code> or <code>g_replyGreater</code> 
  if <code>anItem</code> is less than or greater than 
  list's item respectively.
  </p>
  <p>This is a customized function provided by the item's library 
  and is NOT compulsory.
  </p>
  @param list the one way list.
  @param anItem the given item to compare 
    against the current item within the list.
  @return Return <code>g_replyEqual</code> 
    if <code>anItem</code> and list's item are equal.
    Returns <code>g_replyLesser</code> or <code>g_replyGreater</code> 
    if <code>anItem</code> is less than or greater than 
    list's item respectively.
    Otherwise <code>g_replyFail</code> for failure.
  */
  g_reply (*compareItem)(const oneWayList list, const void *anItem2);
  /*--- item */
  /** Obtain the item of the currently pointing item in the list. 
  <p><b>WARNING:</b> Function will free items in the one way list as well, 
  via the call to <code>boolean (*freeItem)(void **)</code>.
  </p>
  <p>Do NOT free anything taken out of item, 
  e.g. via function pointer call to
  <code>void *(*getItem)(const oneWayList)</code>.
  Because the one way list still points to the item. 
  Thus the item in a sense still sits inside the list so
  it's memory will be free by this function.
  </p>
  <p>However you can free the item IF 
  <ul>
  <li>(1) the item's library say so, such as the item's "free" function 
  which is our function pointer <code>boolean (*freeItem)(void **)</code> 
  couldn't and doesn't handle it.
  Thus requiring external program to handle this.
  e.g. Cloned data struct (which it doesn't keep track of).
  </li>
  <li>(2) You SHOULD free this "cloned" copy of the item cloned from the list.
  The list does NOT keep track of these "clones" and shouldn't release them..
  <br/>UNLESS the item does some trick to <b>keep track of it's own clone</b>, 
  AND also release them via the same function pointer call to 
  <code>boolean (*freeItem)(void **)</code>.
  <br/><b>Advice:</b> Read the item's library details.
  </li>
  </ul>
  </p>
  @param list the one way list.
  @return the currently pointing item in the list.
  */
  void *(*getItem)(const oneWayList list);
  /** Obtain a "cloned" copy of the item currently pointing to in the list. 
  <p>This is a customized function provided by the item's library 
  and is NOT compulsory.
  </p>
  <p>The customized function is given to the list via function pointer
  <code>boolean (*setFnItemClone)(oneWayList, 
      void *(*itemClone)(const void *, const void *))</code>.
  </p>
  <p>You SHOULD free this "cloned" copy of the item cloned from the list.
  The list does NOT keep track of these "clones" and shouldn't release them..
  <br/>UNLESS the item does some trick to <b>keep track of it's own clone</b>, 
  AND also release them via the same function pointer call to 
  <code>boolean (*freeItem)(void **)</code>.
  <br/><b>Advice:</b> Read the item's library for details.
  </p>
  @param list the one way list.
  @param aControlObj an object that customized function may work with,
    e.g. provide cloning ability, other facility and perform other duty.
  @return a "cloned" copy of the item currently pointing to in the list, or
    <code>NULL</code> if failure.
  */
  void *(*getItemClone)(const oneWayList list, const void *aControlObj);
  /** Add this item after the current one in the list.
  Allow item to be <code>NULL</code>.
  <p><b>WARNING:</b> once the item is added into this one way list.
  The one way list will handle freeing the item's memory, 
  via call to function pointer <code>boolean (*freeItem)(void **)</code>.
  </p>
  <p><b>NEVER release memory of the item, once you've added into the list, 
  UNLESS your copy is a clone of the one inside the list.</b> 
  You have to handle freeing memory of the clone.
  The list will handle freeing the item it is pointing to.
  </p>
  <p>The 2 possibility of item memory will be release by the one way list are 
  when (1) the item is deleted via call to function pointer
  <code>boolean (*deleteItem)(oneWayList)</code>,
  or (2) freeing one way list memory via call to function pointer
  <code>boolean (*free)(oneWayList *)</code>.
  </p>
  @param list the one way list.
  @param anItem the item to be added.
  @return true if successfully added the item, false otherwise.
  */
  boolean (*addItem)(oneWayList list, void *anItem);
  /** Delete the current item from the list. 
  After deletion the new current item will become the next item if it exist, 
  otherwise the new current item will become the item in front if it exist.
  If no item exist in front or to the back, the list is empty, 
  current has no item and points to <code>NULL</code>.
  <p>WARNING: There is speed penalty, if deleting item at end of list 
  since after the deletion the list will traverse from start 
  to re-position itself (the current pointer) at the end of list.
  </p>
  <p>NOTE: One way list is made for adding unordered short list, 
  with small foot print and using simple loop to retrieve its' items. 
  If individual item deletion is required recommend to use other library. 
  </p>
  @param list the one way list.
  @return <code>true</code> if successfully otherwise <code>false</code>.
  */
  boolean (*deleteItem)(oneWayList list);
  /*--- provide customized function */
  /** Provide a function to clone an item of type <code>void *</code>.
  The function is of the form 
  <code>void *(*itemClone)(const void *, const void *)</code>.
  <p>This is a customized function provided by the item's library 
  and is NOT compulsory.
  </p>
  <p>You SHOULD free this "cloned" copy of the item cloned from the list.
  The list does NOT keep track of these "clones" and shouldn't release them..
  <br/>UNLESS the item does some trick to <b>keep track of it's own clone</b>, 
  AND also release them via the same function pointer call to 
  <code>boolean (*freeItem)(void **)</code>.
  <br/><b>Advice:</b> Read the item's library for details.
  </p>
  @param list the one way list.
  @param itemClone the function to clone an item of type <code>void *</code>.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*setFnItemClone)(oneWayList list, 
      void *(*itemClone)(const void *anItem, const void *aControlObj));
  /** Provide a function to compare two items of type <code>void *</code>.
  The function is of the form 
  <code>g_reply (*compareItem)(const void *, const void *)</code>.
  <p>This function will be used for comparing a given item against 
  the item currently pointing to within in the list.
  <br/><code>anItem1</code> is the given item.
  <br/><code>anItem2</code> is the current item within the list.
  </p>
  <p><code>compareItem</code> should return <code>g_replyEqual</code> 
  if <code>anItem1</code> and <code>anItem2</code> are equal.
  Returns <code>g_replyLesser</code> or <code>g_replyGreater</code> 
  if <code>anItem1</code> is less than or greater than 
  <code>anItem2</code> respectively.
  </p>
  <p>This is a customized function provided by the item's library 
  and is NOT compulsory.
  </p>
  @param list the one way list.
  @param compareItem the function to compare 
    two items of type <code>void *</code>.
  @return <code>true</code> if successful otherwise <code>false</code>.
  */
  boolean (*setFnCompareItem)(oneWayList list, 
      g_reply (*compareItem)(const void *anItem1, const void *anItem2));
};

/** Create a new oneWayList.
<p>MUST provide a function to free an item of type <code>void *</code>.
The function is of the form <code>boolean (*freeItem)(void **)</code>.
</p>
@param freeItem the function to free an item of type <code>void *</code>.
@return a newly created and empty oneWayList, 
  or <code>NULL</code> if failure.
*/
oneWayList yoneWayList_create(boolean (*freeItem)(void **anItemP));
/** Create a new oneWayList with this item.
<p>MUST provide a function to free an item of type <code>void *</code>.
The function is of the form <code>boolean (*freeItem)(void **)</code>.
</p>
@param anItem the item to be added.
@param freeItem the function to free an item of type <code>void *</code>.
@return a newly created oneWayList with item, 
  or <code>NULL</code> if failure.
*/
oneWayList yoneWayList_createWithItem(void *anItem, 
    boolean (*freeItem)(void **anItemP));

#endif /* _YONEWAYLIST_H */
